'''
This module contains all the commands that can be used globally in the pipeline.
Expressions and other scripts are executed from within this module.
'''

import main

global script_space
script_space = {}

global app

import core.base

def reload():
    for name, value in globals().items():
        if callable(value):
            script_space[name] = value
            
    globals()['app'] = main.App.Current
    script_space['app'] = main.App.Current
    for comp_type in app.scene.types():
        globals()[comp_type.__name__] = comp_type
        script_space[comp_type.__name__] = comp_type

def expression_editor(obj):
    return app.expression_editor(obj)

def root_nodes():
    return app.scene.db.root_nodes()

def is_component(obj):
    return isinstance(obj, core.base.ComponentBase)

def is_plugin(obj):
    return isinstance(obj, core.base.Plugin)

def is_type(obj):
    return isinstance(obj, core.base.ComponentMeta)


def new_type(name):
    import core.manager
    core.manager.PluginManager().new_component_plugin(core.base.Node, name)

def unloaded_components():
    return app.scene.stem_components.values()

def plugins():
    return app.plugins()

def attrs(type):
    if type is None: return
    result = []
    for name, attr in type.attrs():
        result.append(attr)
    return result
    
def one(type):
    all = ls(type)
    if all: 
        return all[0]

def execute(code):
    global script_space
    reload()
    exec(code, script_space)

def signal(name):
    global app
    return app.signals.get(name)

def signal_names():
    global app
    return app.signals.keys()

def hide_view(view):
    app.main_window.rem_view(view)
    
def show_view(view, pos="left"):
    app.main_window.add_view(view, pos)

def update_ui():
    app.update_ui()
    
def update_views():
    app.main_window.update_views()

def run_ui():
    app.run_ui()

def is_view_visible(view):
    return app.main_window.has_view(view)

def new_component(comp):
    type = get_type(comp)
    return type()

def ls(comp_type, parent=None):
    ''' List all instances of given component type '''
    objects = list(app.scene.instances(comp_type))
    if parent is not None:
        objects = [obj for obj in objects if obj.has_parent(parent)]
    return objects

def dbitems():
    return app.scene.root.items()

def main_window():
    return app.main_window

def curr_comp():
    ''' Return the Current Component (last selected) '''
    return app.current_component
    
def action_menu(obj, widget):
    return app.create_action_menu(obj, widget)
    
def types(base_cls):
    for type in app.scene.types():
        if isinstance(base_cls, str):
            if type.__name__ == base_cls:
                yield type
        elif issubclass(type, base_cls) and type is not base_cls:
            yield type

def select(obj):
    app.select(obj)

def view(type, name):
    for item in ls(type):
        item.name, name
        if item.name == name:
            return item

def get_type(name):
    return app.scene.type_class(name)

def get(name, type=None):
    for item in ls(type):
        item.name, name
        if item.name == name:
            return item

def get(type_name, inst_name):
    return app.scene.get(type_name, inst_name)

def object_from_string(text):
    if ":" in text:
        parts = text.split(':')
        if len(parts) == 2:
            if parts[0] == "Type":
                return get_type(parts[1])
            return get(*parts)

def iscomponent(obj):
    import core.base
    return isinstance(obj, core.base.Component)
    
def editor(obj):
    return app.editor(obj)

def save():
    #return
    #app.scene.db.root._p_note_change()
    app.scene.save()
    #app.scene.print_db()